#include <iostream>
#include "Cache.h"
#include <map>
#include <vector>
#include <array>
#include <tuple>
template <typename... Args>
void Print(const Args &...args)
{
    ((std::cout << args << " "), ...);
    std::cout << std::endl;
}

template <typename sep = std::string, typename... Args>
void PrintWithSep(std::string str1, const Args &...args)
{
    ((std::cout << args << str1), ...);
    std::cout << std::endl;
}
struct Test
{
    Test(std::string name, std::size_t id)
        : _name(name),
          _id(id)
    {
    }
    std::string _name;
    std::size_t _id;
};
void test1()
{
    // Print("hello", 10);
    // PrintWithSep("\t", "hello", 2.10, 387);

    Test t("hello", 16);
    // auto [a, b] = t;
    // auto [a, b](Test("hello", 17));
    auto [a, b]{Test("hello", 17)};
    Print(a, b);
}
void test2()
{
    // 这里打印地址和func打印的地址是不一样的，这不符合全局定义的规则
    cout << &bufferSize << endl;
    // C++17引入了内联变量，保证了相同的全局变量指向同一个地址
    // 同时方便了类内静态变量的声明与定义，定义不需要放在类外
    cout << &cacheSize << endl;
    func();
}
void test3(const std::string str)
{
    std::map<std::string, int> m = {{"Alice", 25}, {"Bob", 30}};
    // 作用域只限定在if-else if-else
    if (auto it = m.find("Alice"); it == m.end())
    {
        Print("not found", '\n');
    }
    else
    {
        Print("found", it->second, '\n');
    }

    // switch也支持了条件语句内部定义变量
    switch (auto it = m[str]; it)
    {
    case 25:
        Print("Alice", '\n');
        return;
    case 30:
        Print("Bob", '\n');
        return;
    }
}

template <typename T>
void PrintTypeInfo(const T &val)
{
    if constexpr (std::is_integral_v<T>)
        Print("is int type", '\n');
    else if constexpr (std::is_floating_point_v<T>)
        Print("is float type", '\n');
    else if constexpr (std::is_pointer_v<T>)
        Print("is pointer type", '\n');
    else
        Print("is other type", '\n');
}

void test4()
{
    PrintTypeInfo(10);
    PrintTypeInfo(3.2f);
    PrintTypeInfo((double)3.2);
    PrintTypeInfo(reinterpret_cast<void *>(10));
}

template <typename T, typename... Args>
void PrintArgs(T &&t, Args &&...args)
{
    std::cout << t;
    if constexpr (sizeof...(args) > 0)
    {
        printf(",");
        PrintArgs(std::forward<Args>(args)...);
    }
    else
        printf("\n");
}
template <typename T>
void procress(const T t)
{
    if constexpr (std::is_same_v<T, int>)
        Print("is int type: ", t);
    else if constexpr (std::is_same_v<std::string, T>)
        Print("is string type: ", t);
    else
    {
        static_assert(std::is_same_v<T, int> || std::is_same_v<std::string, T>, "unsupport type");
    }
}
void test5()
{
    procress(10);
    procress("hello"s);
    // procress(2.24);
    // PrintArgs(4, 1.9, 'c', "hello");
}

// 一元左折叠
template <typename... Args>
bool all(Args... args) { return (... && args); }

// 一元右折叠
template <typename... Args>
int sum(Args... args) { return (args + ...); }

// 二元左折叠
template <typename... Args>
std::string left(Args... args) { return (std::string("##") + ... + args); }
template <typename... Args>
std::string right(Args... args) { return (args + ... + std::string("&&")); }

template <typename... Args>
void print_with_sep(Args &&...args)
{
    auto print_elem = [](const auto &v)
    {
        Print(v, ", ");
    };
    (..., print_elem(args));
}
void test6()
{
    Print(all(true, true, true), '\n');
    Print(all(), '\n');
    Print(sum(1, 2, 3, 4), '\n');
    // Print(sum(), '\n');// 编译错误
    Print(left("cd", "ab"), '\n');
    Print(right("ws", "ed"), '\n');
    print_with_sep(1, "342", "hfa", 3.4f);
    Print(left());
}
void test7()
{
    std::vector ve{1, 2, 3};
    std::vector ve1(10, 1);
    // std::map m1{{"hello", 1}, {"hello1", 2}};//不支持
    std::tuple t1{1, 2, 3, 'c', "chet", 4.0f};
}
int main()
{
    // test1();
    // test2();
    // test3("Alice");
    // test4();
    // test5();
    // test6();
    test7();

    return 0;
}
